using System;
using System.Collections.Generic;
using System.Linq;
using CrystalOfInsanity;
using Styx.Common;
using Styx.CommonBot;
using Styx.Pathing;
using Styx.Plugins;
using Styx;
using Styx.WoWInternals;
using System.Threading;
using Styx.WoWInternals.World;
using Styx.WoWInternals.WoWObjects;

namespace ABFix
{
    public class Houdini : HBPlugin
    {
        
        // ===========================================================
        // Constants
        // ===========================================================

        // ===========================================================
        // Fields
        // ===========================================================


        public static LocalPlayer Me = StyxWoW.Me;

        public static CustomLogging CustomLog = new CustomLogging("Houdini");

        //stuck check interval
        public const int CheckDt = 5;
        //min distance to detect stuck issues
        public const float StuckDistance = 10f;
        //consider being stuck after N stuck detections
        public const int StuckAfter = 3; //while flying
        public const int GroundStuckAfter = 12; //while on ground

        private DateTime _lastCheck = DateTime.MinValue;
        private WoWPoint _lastLocation = WoWPoint.Empty;
        private bool _forceHax;
        private int _stuckChecksGround;
        private int _stuckChecksAir;

        //this means that you're considered to be stuck if you did not move at least STUCK_DISTANCE yards away from
        //a given location after STUCK_AFTER*CHECK_DT seconds.

        //associative list of stuck locations <-> path to safe location
        public Dictionary<uint, Dictionary<WoWPoint, WoWPoint[]>> Hotspots =
            new Dictionary<uint, Dictionary<WoWPoint, WoWPoint[]>>{
                {0, /* Eastern Kingdoms *****************************************************************************/
                    new Dictionary<WoWPoint,WoWPoint[]>{
                        { //twiHighlands->Arathi stuck issue ===> Arathi south bridge bridge
                            new WoWPoint(-2324.421, -4383.512, 545.1072),
                            new[]{
                                new WoWPoint(-2160.283, -3832.621, 329.2303),
                                new WoWPoint(-2183.405, -3204.044, 279.6175),
                                new WoWPoint(-2231.291, -2727.011, 229.4274),
                                new WoWPoint(-2240.349, -2488.396, 162.1002)
                            }
                        }/*************************************************/
                        ,
                        { //Hillsbrad Foothills // Arathi Highlands // Wetlands
                            new WoWPoint(-1876.997, -811.006, 546.8296),
                            new[]{
                                new WoWPoint(-1763.627, -1420.722, 54.18901)
                            }
                        }/*************************************************/
                        ,
                        { //Twilight Highlands \\ Artahi Highlands (going north)
                            new WoWPoint(-2359.228, -4343.515, 547.7906),
                            new[]{
                                new WoWPoint(-3150.852, -4206.659, 358.4099)
                            }
                        }/*************************************************/
                        ,
                        { //Redrige Mountains (stuck east going north)
                            new WoWPoint(-8990.212, -4214.939, 546.9885),
                            new[]{
                                new WoWPoint(-9313.827, -3865.626, 244.6957)
                            }
                        }/*************************************************/
                        ,
                        { //Burning Steppes (stuck east going south)
                            new WoWPoint(-7786.586, -3978.079, 546.9885),
                            new[]{
                                new WoWPoint(-7417.835, -3438.153, 404.075)
                            }
                        }/*************************************************/
                     }
                }
                /****************************************************************************************************/
        };

        // ===========================================================
        // Constructors
        // ===========================================================

        // ===========================================================
        // Getter & Setter
        // ===========================================================

        // ===========================================================
        // Methods for/from SuperClass/Interfaces
        // ===========================================================

        public override string Author {
            get { return "Wigglez (originally by cowdude)"; }
        }

        public override string Name {
            get { return "Houdini"; }
        }

        public override Version Version {
            get { return new Version(1, 2); }
        }

        public override bool WantButton {
            get {
                return true;
            }
        }

        public override string ButtonText {
            get {
                return "Force unstuck";
            }
        }

        public override void OnButtonPress() {
            _forceHax = true;
            
            CustomLog.CustomNormalLog("Unstucking on next pulse");
        }

        // ===========================================================
        // Methods
        // ===========================================================

        public bool Hearthstone() {
            if(!StyxWoW.IsInGame || StyxWoW.Me.IsCasting)
                return false;

            //hearthstone or fucking innkeeper's bitch
            var h = Me.BagItems.FirstOrDefault(x => x.Entry == 6948 || x.Entry == 64488);
            if(h == null) {

                CustomLog.CustomNormalLog("No hearthstone found in bags.");
                return true; //who knows...
            }

            if(h.Cooldown > 0)
                return true;

            h.Use();

            return false;
        }

        // ===========================================================
        // Inner and Anonymous Classes
        // ===========================================================

        //a stupid helper class to detect mounting
        private static class FreakingMountHelper
        {
            public delegate void OnMountingDelegate();
            public static event OnMountingDelegate OnMounting;

            public delegate void OnMountLoopDetectedDelegate();
            public static event OnMountLoopDetectedDelegate OnMountLoopDetected;

            public static bool IsAttached { get { return _isAttached; } }

            private static bool _isAttached;
            public static void Init()
            {
                Lua.Events.AttachEvent("UNIT_SPELLCAST_SUCCEEDED", OnSpellStartHook);
                _timer = DateTime.Now;
                _count = 0;
                _castingMountSpell = false;
                OnMounting = null;
                OnMountLoopDetected = null;
                _isAttached = true;
            }

            private static int _count;
            private static bool _castingMountSpell;
            private static DateTime _timer;

            private const int DT = 30; //seconds
            private const double MaxMpm = 15; //max mounts per minute attempts, successful or not

            private static void OnSpellStartHook (object sender, LuaEventArgs lua) {
                var args = lua.Args;
                var unit = (string) args[0];
                //Logging.WriteDebug("XXX CAST XXX: args = {0},{1},{2},{3},{4} -> '{5}'",
                //    args[0], args[1], args[2], args[3], args[4], unit);
                if (unit != "player")
                    return;

                var spellId = (int)(double)args[4];
                //Logging.Write(" => SPELL ID = " + spellId);

                _castingMountSpell = FuckingMountList.Contains(spellId);
                if (_castingMountSpell)
                {
                    _count++;

                    CustomLog.CustomDiagnosticLog("Detected mount spell casting ({0}/{1}).", _count, MaxMpm);

                    if (OnMounting != null)
                        OnMounting();
                }
            }

            public static void Pulse()
            {
                if (DateTime.Now.Subtract(_timer).TotalSeconds > DT)
                {
                    double mountsPerMinute = _count / (double)DT * 60.0;
                    _count = 0;
                    _timer = DateTime.Now;
                    if (mountsPerMinute > MaxMpm)
                    {
                        CustomLog.CustomNormalLog("Tried to mount {0} times in {1} seconds, woopsie.", _count, DT);

                        if (OnMountLoopDetected != null)
                            OnMountLoopDetected();
                    }
                }
            }
        }

        

        

        private WoWPoint[] SafePath
        {
            get
            {
                ObjectManager.Update();
                if (!Hotspots.ContainsKey(StyxWoW.Me.MapId))
                {
                    CustomLog.CustomNormalLog("WARN: Cannot find current continent ({0}) in the safespots list.", StyxWoW.Me.MapId);
                   
                    return null;
                }

                var score = (float)(200*200); //square of max distance to a valid stuck location
                WoWPoint[] best = null;
                var assoc = Hotspots[StyxWoW.Me.MapId];
                foreach (var pair in assoc)
                {
                    var testScore = pair.Key.DistanceSqr(StyxWoW.Me.Location);
                    if (testScore < score)
                    {
                        score = testScore;
                        best = pair.Value;
                    }
                }
                if (best == null)
                    CustomLog.CustomNormalLog("WARN: Could not find any safespot on this continent.");
                return best;
            }
        }

        

        public override void Pulse()
        {
            //ensure the mount helper is running fine here
            if (!FreakingMountHelper.IsAttached)
            {
                CustomLog.CustomNormalLog("Initializing the freaking mount helper...");
                FreakingMountHelper.Init();
                FreakingMountHelper.OnMounting += FreakingMountHelper_OnMounting;
                FreakingMountHelper.OnMountLoopDetected += FreakingMountHelper_OnMountLoopDetected;
            }

            if (StyxWoW.Me.Combat || !StyxWoW.Me.IsAlive || Battlegrounds.IsInsideBattleground)
            {
                _stuckChecksGround = 0;
                _stuckChecksAir = 0;
                _lastCheck = DateTime.Now;
                return;
            }

            //detect mount loops
            FreakingMountHelper.Pulse();

            if (_forceHax)
            {
                CustomLog.CustomNormalLog("***** User forced unstuck process. Running dirty hax fix. *****");
                _lastLocation = StyxWoW.Me.Location;
                _lastCheck = DateTime.Now;
                _forceHax = false;
                _stuckChecksGround = 0;
                _stuckChecksAir = 0;
                new Thread(Hax).Start();
            }
            else if (DateTime.Now.Subtract(_lastCheck).TotalSeconds > CheckDt)
            {
                //Ground stuck detections - a bit slower because of some AB bugs making the toon stand still for 30s
                if (!Flightor.MountHelper.Mounted)
                {
                    if (_lastLocation != WoWPoint.Empty && StyxWoW.Me.Location.Distance(_lastLocation) <= GroundStuckAfter)
                    {
                        Logging.Write("ABFix: Ground stuck detected ({0}/{1})", _stuckChecksGround + 1, GroundStuckAfter);
                        _lastCheck = DateTime.Now;

                        //we're not updating lastLocation: stuck checks must use the same 'old' location!

                        //too much stuck detected -> bang.
                        if (++_stuckChecksGround >= GroundStuckAfter)
                        {
                            CustomLog.CustomNormalLog("***** Detected stuck issue. Running dirty hax fix. *****");
                            _lastLocation = StyxWoW.Me.Location;
                            _stuckChecksGround = 0;
                            _stuckChecksAir = 0;
                            new Thread(Hax).Start();
                        }
                    }
                    else
                    {
                        if (_stuckChecksGround > 0)
                            CustomLog.CustomNormalLog("Reset stuck check counter.");
                        _stuckChecksGround = 0;
                        _stuckChecksAir = 0;
                        _lastLocation = StyxWoW.Me.Location;
                        _lastCheck = DateTime.Now;
                    }
                }
                //Flying stuck issues - pretty rare, but it happens...
                else
                {
                    if (_lastLocation != WoWPoint.Empty && StyxWoW.Me.Location.Distance(_lastLocation) <= StuckDistance)
                    {
                        CustomLog.CustomNormalLog("Stuck while flying detected ({0}/{1})", _stuckChecksAir + 1, StuckAfter);
                        _lastCheck = DateTime.Now;

                        //we're not updating lastLocation: stuck checks must use the same 'old' location!

                        //too much stuck detected -> bang.
                        if (++_stuckChecksAir >= StuckAfter)
                        {
                            CustomLog.CustomNormalLog("***** Detected stuck issue. Running dirty hax fix. *****");
                            _lastLocation = StyxWoW.Me.Location;
                            _stuckChecksGround = 0;
                            _stuckChecksAir = 0;
                            new Thread(Hax).Start();
                        }
                    }
                    else
                    {
                        if (_stuckChecksAir > 0)
                            CustomLog.CustomNormalLog("Reset stuck check counter.");
                        _stuckChecksGround = 0;
                        _stuckChecksAir = 0;
                        _lastLocation = StyxWoW.Me.Location;
                        _lastCheck = DateTime.Now;
                    }
                }
            }
        }

        void FreakingMountHelper_OnMounting()
        {
            CustomLog.CustomNormalLog("Mount attempt => reset stuck count.");
            _stuckChecksGround = 0;
            _stuckChecksAir = 0;
        }

        void FreakingMountHelper_OnMountLoopDetected()
        {
            //run the unstuck behavior
            if (TreeRoot.IsRunning)
            {
                CustomLog.CustomNormalLog("***** Detected mount loop stuck issue. Running dirty hax fix. *****");
                _lastLocation = StyxWoW.Me.Location;
                _lastCheck = DateTime.Now;
                _forceHax = false;
                _stuckChecksGround = 0;
                _stuckChecksAir = 0;
                new Thread(Hax).Start();
            }
        }

        public void Hax()
        {
            CustomLog.CustomNormalLog("Stopping bot...");
            TreeRoot.Stop();
            Thread.Sleep(10000);

            //safespot logic
            var safe = SafePath;
            if (safe != null)
            {
                CustomLog.CustomNormalLog("Found safespot of {1} nodes: {0}", safe.Last(), safe.Length);

                int tries = 0;
                while (!Flightor.MountHelper.Mounted)
                {
                    if (++tries >= 5)
                    {
                        Logging.Write("ABFix: Failed to mount. Switching to hearthstone logic...");
                        safe = null;
                        break;
                    }

                    ObjectManager.Update();

                    if (StyxWoW.Me.Combat || !StyxWoW.Me.IsAlive)
                    {
                        CustomLog.CustomNormalLog("Got in combat or died while trying to mount up! Restarting bot....");
                        _lastCheck = DateTime.MinValue;
                        _lastLocation = StyxWoW.Me.Location;
                        TreeRoot.Start();
                        return;
                    }

                    Logging.Write("ABFix: Mounting up...");
                    Flightor.MountHelper.MountUp();
                    Thread.Sleep(5000);
                }

                if (safe != null)
                {
                    ObjectManager.Update();

                    if(StyxWoW.Me.Combat || !StyxWoW.Me.IsAlive)
                    {
                        CustomLog.CustomNormalLog("Got in combat or died while moving to safespot! Restarting bot....");
                        _lastCheck = DateTime.MinValue;
                        _lastLocation = StyxWoW.Me.Location;
                        TreeRoot.Start();
                        return;
                    }

                    int index = 0;
                    while (index < safe.Length)
                    {
                        ObjectManager.Update();
                        var d = safe[index].Distance(StyxWoW.Me.Location);
                        if (d < 6f)
                        {
                            index++;
                            CustomLog.CustomNormalLog("Reached node {0}/{1}", index, safe.Length);
                        }
                        else
                        {
                            WoWMovement.ClickToMove(safe[index]);
                            CustomLog.CustomNormalLog("Moving to safespot {0}/{1}. D = {2}",
                                index + 1, safe.Length, Math.Round(d, 2));
                            Thread.Sleep(1000);
                        }
                    }
                    Logging.Write("ABFix: Reached safespot!");
                }
            }

            if (safe == null)
            {
                //old hearthstone logic
                CustomLog.CustomNormalLog("Could not find a safespot on this continent! Using hearthstone logic...");
                if (Flightor.MountHelper.Mounted)
                {
                    CustomLog.CustomNormalLog("Player is mounted... got to land somewhere!!");


                    WoWPoint ground;
                    var down = StyxWoW.Me.Location.Add(0, 0, -16000);
                    GameWorld.TraceLine(StyxWoW.Me.Location, down,
                        GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures |
                        GameWorld.CGWorldFrameHitFlags.HitTestLiquid |
                        GameWorld.CGWorldFrameHitFlags.HitTestLiquid2, out ground);

                    if (ground == WoWPoint.Empty)
                    {
                        //happens when player is stuck on the fatigue wall.
                        CustomLog.CustomNormalLog("Could not find ground...woops... dismounting and praying.");
                        Mount.Dismount();
                        Thread.Sleep(3000);
                        while (StyxWoW.Me.IsFalling && !StyxWoW.Me.IsAlive)
                        {
                            CustomLog.CustomNormalLog("Oh noes, I'm falling.");
                            Thread.Sleep(1000);
                            ObjectManager.Update();
                        }
                        CustomLog.CustomNormalLog("I survived!");
                    }
                    else
                    {
                        CustomLog.CustomNormalLog("Moving to ground...");
                        while (StyxWoW.Me.Location.Distance(ground) > 10f)
                        {
                            WoWMovement.ClickToMove(down);
                            ObjectManager.Update();
                            Thread.Sleep(250);
                        }

                        CustomLog.CustomNormalLog("Dismounting!");
                        Mount.Dismount();
                        Thread.Sleep(3000);
                    }
                }

                CustomLog.CustomNormalLog("Using hearthstone...");
                while (!Hearthstone() /*|| StyxWoW.Me.ZoneId != StyxWoW.Me.HearthstoneAreaId*/)
                {
                    if(StyxWoW.Me.Combat || !StyxWoW.Me.IsAlive)
                    {
                        CustomLog.CustomNormalLog("Got in combat or died while trying to hearthstone! Restarting bot....");
                        _lastCheck = DateTime.MinValue;
                        _lastLocation = StyxWoW.Me.Location;
                        TreeRoot.Start();
                        return;
                    }

                    //Logging.Write("Me.Zone = {0}, Me.HearthstoneArea = {1}",
                    //    StyxWoW.Me.ZoneId, StyxWoW.Me.HearthstoneAreaId);
                    ObjectManager.Update();
                    Thread.Sleep(1000);
                }

                CustomLog.CustomNormalLog("Hearthstone process complete, assuming it worked...");

                while (!StyxWoW.IsInGame)
                {
                    CustomLog.CustomNormalLog("Not in game...");
                    ObjectManager.Update();
                    Thread.Sleep(1000);
                }
            }


            CustomLog.CustomNormalLog("starting bot...");
            TreeRoot.Start();

            CustomLog.CustomNormalLog("Successfuly hax-fixed the damn stuck issue. yay.");
        }

        
        //source: wowhead.
        public static readonly HashSet<int> FuckingMountList = new HashSet<int>{
            33943, //flight form
            40120, //swift flight form
            61451, //@Flying Carpet
            75596, //@Frosty Flying Carpet
            61309, //@Magnificent Flying Carpet
            93644, //@Kor'kron Annihilator
            23509, //@Frostwolf Howler
            75207, //@Abyssal Seahorse
            67466, //@Argent Warhorse
            66907, //@Argent Warhorse
            36702, //@Fiery Warhorse
            68187, //@Crusader's White Warhorse
            64656, //@Blue Skeletal Warhorse
            65645, //@White Skeletal Warhorse
            23246, //@Purple Skeletal Warhorse
            66846, //@Ochre Skeletal Warhorse
            22722, //@Red Skeletal Warhorse
            17465, //@Green Skeletal Warhorse
            68188, //@Crusader's Black Warhorse
            63643, //@Forsaken Warhorse
            17463, //@Blue Skeletal Horse
            17464, //@Brown Skeletal Horse
            64977, //@Black Skeletal Horse
            17462, //@Red Skeletal Horse
            458, //@Brown Horse
            63796, //@Mimiron's Head
            88749, //@Tan Riding Camel
            88750, //@Grey Riding Camel
            88748, //@Brown Riding Camel
            6898, //@White Ram
            23240, //@Swift White Ram
            23510, //@Stormpike Battle Charger
            17460, //@Frost Ram
            63636, //@Ironforge Ram
            22720, //@Black War Ram
            43899, //@Brewfest Ram
            43900, //@Swift Brewfest Ram
            6777, //@Gray Ram
            23239, //@Swift Gray Ram
            6899, //@Brown Ram
            23238, //@Swift Brown Ram
            17461, //@Black Ram
            65643, //@Swift Violet Ram
            40192, //@Ashes of Al'ar
            60424, //@Mekgineer's Chopper
            46197, //@X-51 Nether-Rocket
            46199, //@X-51 Nether-Rocket X-TREME
            75973, //@X-53 Touring Rocket
            54729, //@Winged Steed of the Ebon Blade
            23228, //@Swift White Steed
            75614, //@Celestial Steed
            22717, //@Black War Steed
            68057, //@Swift Alliance Steed
            63232, //@Stormwind Steed
            92231, //@Spectral Steed
            65640, //@Swift Gray Steed
            23229, //@Swift Brown Steed
            23161, //@Dreadsteed
            66090, //@Quel'dorei Steed
            5784, //@Felsteed
            66906, //@Argent Charger
            73313, //@Crimson Deathcharger
            48778, //@Acherus Deathcharger
            17481, //@Rivendare's Deathcharger
            58615, //@Brutal Nether Drake
            44744, //@Merciless Nether Drake
            37015, //@Swift Nether Drake
            49193, //@Vengeful Nether Drake
            41514, //@Azure Netherwing Drake
            41513, //@Onyx Netherwing Drake
            41515, //@Cobalt Netherwing Drake
            41516, //@Purple Netherwing Drake
            41517, //@Veridian Netherwing Drake
            41518, //@Violet Netherwing Drake
            60025, //@Albino Drake
            59568, //@Blue Drake
            59567, //@Azure Drake
            59569, //@Bronze Drake
            59571, //@Twilight Drake
            93326, //@Sandstone Drake
            69395, //@Onyxian Drake
            88718, //@Phosphorescent Stone Drake
            88746, //@Vitreous Stone Drake
            88331, //@Volcanic Stone Drake
            88335, //@Drake of the East Wind
            88742, //@Drake of the North Wind
            88741, //@Drake of the West Wind
            88744, //@Drake of the South Wind
            93623, //@Mottled Drake
            59650, //@Black Drake
            59570, //@Red Drake
            66088, //@Sunreaver Dragonhawk
            61996, //@Blue Dragonhawk
            61997, //@Red Dragonhawk
            63639, //@Exodar Elekk
            48027, //@Black War Elekk
            35710, //@Gray Elekk
            34406, //@Brown Elekk
            35711, //@Purple Elekk
            88990, //@Dark Phoenix
            65917, //@Magic Rooster
            71342, //@Big Love Rocket
            35713, //@Great Blue Elekk
            35714, //@Great Purple Elekk
            65637, //@Great Red Elekk
            35712, //@Great Green Elekk
            23247, //@Great White Kodo
            49379, //@Great Brewfest Kodo
            65641, //@Great Golden Kodo
            23248, //@Great Gray Kodo
            23249, //@Great Brown Kodo
            61465, //@Grand Black War Mammoth
            61467, //@Grand Black War Mammoth
            61469, //@Grand Ice Mammoth
            61470, //@Grand Ice Mammoth
            58983, //@Big Blizzard Bear
            32242, //@Swift Blue Gryphon
            32239, //@Ebon Gryphon
            32235, //@Golden Gryphon
            32292, //@Swift Purple Gryphon
            32240, //@Snowy Gryphon
            61229, //@Armored Snowy Gryphon
            32289, //@Swift Red Gryphon
            32290, //@Swift Green Gryphon
            66091, //@Sunreaver Hawkstrider
            35020, //@Blue Hawkstrider
            46628, //@Swift White Hawkstrider
            63642, //@Silvermoon Hawkstrider
            35018, //@Purple Hawkstrider
            35027, //@Swift Purple Hawkstrider
            35022, //@Black Hawkstrider
            34795, //@Red Hawkstrider
            65639, //@Swift Red Hawkstrider
            33660, //@Swift Pink Hawkstrider
            35025, //@Swift Green Hawkstrider
            63844, //@Argent Hippogryph
            66087, //@Silver Covenant Hippogryph
            43927, //@Cenarion War Hippogryph
            74856, //@Blazing Hippogryph
            72286, //@Invincible
            13819, //@Summon Warhorse
            34769, //@Summon Warhorse
            23214, //@Summon Charger
            34767, //@Summon Charger
            73629, //@Summon Exarch's Elekk
            73630, //@Summon Great Exarch's Elekk
            69826, //@Summon Great Sunwalker Kodo
            69820, //@Summon Sunwalker Kodo
            32296, //@Swift Yellow Wind Rider
            32244, //@Blue Wind Rider
            61230, //@Armored Blue Wind Rider
            32243, //@Tawny Wind Rider
            32297, //@Swift Purple Wind Rider
            32246, //@Swift Red Wind Rider
            32245, //@Green Wind Rider
            32295, //@Swift Green Wind Rider
            18992, //@Teal Kodo
            64657, //@White Kodo
            63641, //@Thunder Bluff Kodo
            22718, //@Black War Kodo
            50869, //@Brewfest Kodo
            18989, //@Gray Kodo
            18990, //@Brown Kodo
            18991, //@Green Kodo
            65646, //@Swift Burgundy Wolf
            22724, //@Black War Wolf
            68056, //@Swift Horde Wolf
            63640, //@Orgrimmar Wolf
            92232, //@Spectral Wolf
            580, //@Timber Wolf
            23251, //@Swift Timber Wolf
            23252, //@Swift Gray Wolf
            16081, //@Winter Wolf
            6654, //@Brown Wolf
            23250, //@Swift Brown Wolf
            64658, //@Black Wolf
            16080, //@Red Wolf
            6653, //@Dire Wolf
            41252, //@Raven Lord
            59785, //@Black War Mammoth
            59788, //@Black War Mammoth
            59797, //@Ice Mammoth
            59799, //@Ice Mammoth
            61425, //@Traveler's Tundra Mammoth
            61447, //@Traveler's Tundra Mammoth
            59791, //@Wooly Mammoth
            59793, //@Wooly Mammoth
            44153, //@Flying Machine
            44151, //@Turbo-Charged Flying Machine
            55531, //@Mechano-Hog
            23222, //@Swift Yellow Mechanostrider
            10969, //@Blue Mechanostrider
            17459, //@Icy Blue Mechanostrider Mod A
            15779, //@White Mechanostrider Mod B
            23223, //@Swift White Mechanostrider
            63638, //@Gnomeregan Mechanostrider
            10873, //@Red Mechanostrider
            17454, //@Unpainted Mechanostrider
            17453, //@Green Mechanostrider
            23225, //@Swift Green Mechanostrider
            89520, //@Goblin Mini Hotrod
            48025, //@Headless Horseman's Mount
            51412, //@Big Battle Bear
            43688, //@Amani War Bear
            60118, //@Black War Bear
            60119, //@Black War Bear
            60114, //@Armored Brown Bear
            60116, //@Armored Brown Bear
            54753, //@White Polar Bear
            16082, //@Palomino
            23227, //@Swift Palomino
            32345, //@Peep the Phoenix Mount
            472, //@Pinto
            60021, //@Plagued Proto-Drake
            59996, //@Blue Proto-Drake
            63963, //@Rusted Proto-Drake
            59976, //@Black Proto-Drake
            59961, //@Red Proto-Drake
            60002, //@Time-Lost Proto-Drake
            61294, //@Green Proto-Drake
            63956, //@Ironbound Proto-Drake
            60024, //@Violet Proto-Drake
            23241, //@Swift Blue Raptor
            22721, //@Black War Raptor
            8395, //@Emerald Raptor
            84751, //@Fossilized Raptor
            63635, //@Darkspear Raptor
            17450, //@Ivory Raptor
            65644, //@Swift Purple Raptor
            23243, //@Swift Orange Raptor
            23242, //@Swift Olive Raptor
            24242, //@Swift Razzashi Raptor
            16084, //@Mottled Red Raptor
            10796, //@Turquoise Raptor
            10799, //@Violet Raptor
            64659, //@Venomhide Ravasaur
            39803, //@Blue Riding Nether Ray
            39801, //@Purple Riding Nether Ray
            39802, //@Silver Riding Nether Ray
            39800, //@Red Riding Nether Ray
            39798, //@Green Riding Nether Ray
            90621, //@Golden King
            74918, //@Wooly White Rhino
            16056, //@Ancient Frostsaber
            17229, //@Winterspring Frostsaber
            10789, //@Spotted Frostsaber
            23221, //@Swift Frostsaber
            8394, //@Striped Frostsaber
            65638, //@Swift Moonsaber
            23219, //@Swift Mistsaber
            63637, //@Darnassian Nightsaber
            16055, //@Black Nightsaber
            10793, //@Striped Nightsaber
            23338, //@Swift Stormsaber
            66847, //@Striped Dawnsaber
            16083, //@White Stallion
            470, //@Black Stallion
            34897, //@White War Talbuk
            34899, //@Tan War Talbuk
            34896, //@Cobalt War Talbuk
            34790, //@Dark War Talbuk
            34898, //@Silver War Talbuk
            39319, //@White Riding Talbuk
            39318, //@Tan Riding Talbuk
            39315, //@Cobalt Riding Talbuk
            39316, //@Dark Riding Talbuk
            39317, //@Silver Riding Talbuk
            26055, //@Yellow Qiraji Battle Tank
            25953, //@Blue Qiraji Battle Tank
            26656, //@Black Qiraji Battle Tank
            26054, //@Red Qiraji Battle Tank
            92155, //@Ultramarine Qiraji Battle Tank
            26056, //@Green Qiraji Battle Tank
            22723, //@Black War Tiger
            42776, //@Spectral Tiger
            42777, //@Swift Spectral Tiger
            24252, //@Swift Zulian Tiger
            30174, //@Riding Turtle
            64731, //@Sea Turtle
            87090, //@Goblin Trike
            87091, //@Goblin Turbo-Trike
            65642, //@Turbostrider
            72808, //@Bloodbathed Frostbrood Vanquisher
            72807, //@Icebound Frostbrood Vanquisher
            71810, //@Wrathful Gladiator's Frost Wyrm
            65439, //@Furious Gladiator's Frost Wyrm
            67336, //@Relentless Gladiator's Frost Wyrm
            64927, //@Deadly Gladiator's Frost Wyrm
            6648, //@Chestnut Mare
            22719, //@Black Battlestrider
            35028, //@Swift Warstrider
            49322 //@Swift Zhevra
        };
    }
}
